<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Auth {
	
	 /** @var object A pointer to the CodeIgniter instance. */
    private $ci;

    /** @var string The ip_address of the current user. */
	private $ip_address;

    /** @var array The names of all existing permissions. */
    private $permissions = null;

    /** @var array The info of all existing permissions. */
    private $permissions_info = null;

    /** @var array The permissions by role. */
	private $role_permissions = array();

    /** @var object The logged-in user. */
    private $user;
	
	/**
     * Grab a pointer to the CI instance, get the user's IP address, and attempt
     * to automatically log in the user.
	 *
	 * @return void
	 */
	public function __construct()
	{
		$this->ci =& get_instance();

		$this->ip_address = $this->ci->input->ip_address();
		log_message('debug', 'Auth class initialized.');
    }
	
	
	/**
     * Check whether a user is logged in (and, optionally of the correct role) and,
     * if not, send them to the login screen.
	 *
	 * If no permission is checked, will simply verify that the user is logged in.
     * If a permission is passed in to the first parameter, it will check the user's
     * role and verify that role has the appropriate permission.
	 *
     * @param string $permission (Optional) The permission to check for.
     * @param string $uri        (Optional) The redirect URI if the user does not
     * have the correct permission.
	 *
     * @return bool True if the user has the appropriate access permissions.
     * Redirect to the previous page if the user doesn't have permissions.
     * Redirect to LOGIN_AREA page if the user is not logged in.
	 */
	function restrict($permission = null, $uri = null)
	{
		$permission = strtolower($permission);
		$permissions = $this->loadPermissions();
		$role_permissions = $this->loadRolePermissions();
		$permission_id = @$permissions[$permission];
		
		if($uri == null) $uri = admin_url().'nopermission.html';
		if(!$this->has_permission($permission))
		{
			redirect($uri);
		}
	}

    function get_info($permission)
    {
        // Move permission to lowercase for easier checking.
        $permission = strtolower($permission);

         $this->loadPermissions();
        if (isset($this->permissions_info[$permission])) {
            return $this->permissions_info[$permission];
        }
        return FALSE;
    }
	//--------------------------------------------------------------------------
    // Permissions
    //--------------------------------------------------------------------------

    /**
     * Verify that the user is logged in and has the appropriate permissions.
     *
     * @param string $permission The permission to check for, e.g. 'Site.Signin.Allow'.
     * @param int    $role_id    The id of the role to check the permission against.
     * If role_id is not passed into the method, it assumes the current user's role_id.
     * @param bool   $override   Whether access is granted if this permission doesn't
     * exist in the database.
     *
     * @return bool True if the user/role has permission or $override is true and
     * the permission was not found in the database, else false.
     */
	function has_permission($permission, $role_id = null, $override = false)
	{
		// Move permission to lowercase for easier checking.
        $permission = strtolower($permission);

        // If no role is provided, assume it's for the current logged in user.
        if (empty($role_id)) {
            $role_id = $this->role_id();
        }

        $permissions = $this->loadPermissions();

        // Does the user/role have the permission?
        if (isset($permissions[$permission])) {
            $role_permissions = $this->loadRolePermissions($role_id);
            $permission_id    = $permissions[$permission];
			
            if (isset($role_permissions[$role_id][$permission_id])) {
                return true;
            }
        } elseif ($override) {
            return true;
        }

        return false;
	}
	
	/**
     * Load the permission names from the database.
	 *
     * @return array Permissions: key - lowercase name, value - permission ID.
	 */
    private function loadPermissions()
	{
        if (! empty($this->permissions)) {
            return $this->permissions;
		}

        if (! class_exists('permission_m')) {
            $this->ci->load->model('permission_m','permission');
		}

        $this->permissions = array();
        $perms = $this->ci->permission->get_many_by();
        foreach ($perms as $perm) {
            $this->permissions[strtolower($perm->permission_name)] = $perm->permission_id;
            $this->permissions_info[strtolower($perm->permission_name)] = $perm;

        }

        return $this->permissions;
    }
	
	
	/**
     * Load the role permissions from the database.
	 *
     * @param int $role_id The role id for which permissions are loaded. Uses
     * the current user's role ID if none is provided.
	 *
	 * @return void
	 */
    private function loadRolePermissions($role_id = null)
	{
		
		if (! class_exists('admin')) {
            $this->ci->load->model('admin_m','admin');
		}

        if (is_null($role_id)) {
            $role_id = $this->role_id();
        }

        if (! empty($this->role_permissions[$role_id])) {
            return $this->role_permissions;
        }

        if (! class_exists('role_permission_m')) {
            $this->ci->load->model('role_permission_m');
		}
		
        $this->role_permissions[$role_id] = array();
        $role_perms = $this->ci->role_permission_m->get_many_by('role_id', $role_id);
        if (! is_array($role_perms)) {
            return $this->role_permissions;
        }

        foreach ($role_perms as $permission) {
            $this->role_permissions[$role_id][$permission->permission_id] = true;
        }

        return $this->role_permissions;
    }
	
	/**
     * Retrieves the role_id from the current session.
	 *
     * @return int The user's role_id.
	 */
    public function role_id()
	{
		if (! $this->is_logged_in()) {
			return false;
		}
		return $this->ci->admin->role_id;
	}
	
	function is_logged_in()
	{
		return $this->ci->admin->checkLogin();
	}
}


//------------------------------------------------------------------------------
// Helper Functions
//------------------------------------------------------------------------------

if (! function_exists('has_permission')) {
	/**
	 * A convenient shorthand for checking user permissions.
	 *
     * @param string $permission The permission to check for, ie 'Site.Signin.Allow'.
     * @param bool   $override   Whether access is granted if this permission doesn't
     * exist in the database.
	 *
     * @return bool True if the user has the permission or $override is true and
     * the permission wasn't found in the system, else false.
	 */
    function has_permission($permission, $override = false)
	{
        return get_instance()->auth->has_permission($permission, null, $override);
    }
}
